package com.sskj.extract;

import org.w3c.dom.*;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Extract {

    private static List<File> fileList = new LinkedList<>();

    private static HashMap<String, String> nameTemp = new HashMap<>();

    private static HashMap<String, String> exitName = new HashMap<>();

    private static int index = 0;
    private static String salt = "";

    private static Document realDocument;

    private enum FileType {
        XML, JAVA, KT, OTHER
    }

    public static void main(String[] args) {
        extract();
    }

    public static void extract() {

        Map<String, String> map = Config.getMap();

        map.forEach((s, s2) -> {
            fileList.clear();
            nameTemp.clear();
            exitName.clear();
            readExitString(s);
            findFile(s + "/src/main/res/layout");
            findFile(s + "/src/main/java");
            for (File file1 : fileList) {
                index = 0;
                readFile(file1, s2);
            }
            editString(s);
            System.out.print("Success 替换个数:" + nameTemp.size());
        });

    }

    public static String isContainChinese(String text, String name, String prefex) {
        index++;
        String t = "\"[^\"^.]*[\\u4e00-\\u9fa5].*?\"";
        Pattern p = Pattern.compile(t);
        Matcher m = p.matcher(text);
        String result = text;
        if (m.find()) {
            String chinese = m.group();
            String realChinese = m.group().substring(1, m.group().length() - 1);
            String newName = cacheName(realChinese, prefex + format(name + index + salt));
            System.out.print("find>>>>" + chinese + "\n");
            System.out.print("Replace>>>>" + newName + "\n");
            result = text.replace(chinese, "App.INSTANCE.getString(R.string." + newName + ")");
            result = isContainChinese(result, name, prefex);
        }
        return result;
    }


    /**
     * 查找文件夹下的文件
     */
    public static void findFile(String path) {
        //文件夹
        File file = new File(path);
        if (file.exists()) {
            if (file.isDirectory()) {
                //文件夹下的文件
                File[] files = file.listFiles();
                if (files != null && files.length > 0) {
                    //遍历文件
                    for (File file1 : files) {
                        if (file1.isDirectory()) {
                            if (!file1.getAbsolutePath().contains("build")) {
                                findFile(file1.getAbsolutePath());
                            }
                        } else {
                            System.out.print(file1.getName() + "\n");
                            fileList.add(file1);
                        }
                    }
                }
            } else {
                System.out.print(file.getName() + "\n");
                fileList.add(file);
            }

        }

    }

    public static void readFile(File file, String prefex) {
        switch (checkFile(file)) {
            case KT:
                autoReplace(file, prefex);
                break;
            case XML:
                readXml(file, prefex);
                break;
            case JAVA:
                autoReplace(file, prefex);
                break;
        }
    }


    public static FileType checkFile(File file) {
        String name = file.getName();
        String typeName = name.substring(name.lastIndexOf(".") + 1).toLowerCase();
        if (typeName.equals("xml")) {
            return FileType.XML;
        }
        if (typeName.equals("java")) {
            return FileType.JAVA;
        }
        if (typeName.equals("kt")) {
            return FileType.KT;
        }
        return FileType.OTHER;
    }


    public static void readJava(File file, String prefex) {
        try {
            String name = file.getName();
            if (name.contains(".")) {
                name = name.substring(0, name.indexOf("."));
            }
            RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
            String line;
            long lastPoint = 0;
            int lineIndex = 0;
            while ((line = randomAccessFile.readLine()) != null) {
                long point = randomAccessFile.getFilePointer();
                line = new String(line.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
                //判断是否含有中文并替换保存
                if (line.length() > 0) {
                    String str = isContainChinese(line, name + lineIndex, prefex);
                    if (!str.equals(line)) {
                        randomAccessFile.seek(lastPoint);
                        randomAccessFile.writeBytes(str);
                    }
                }
                lastPoint = point;
                lineIndex++;
            }
            randomAccessFile.close();

//            String content = useBufferIStream(file);
//            if (content.length() > 0) {
//                String str = isContainChinese(content, name);
//                if (!str.equals(content)) {
//                    BufferedWriter writer;
//                    writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
//                    writer.write(content);
//                    writer.flush();
//                    writer.close();
//                }
//            }

        } catch (IOException e) {
            e.printStackTrace();
        }


    }


    private static void autoReplace(File file, String prefex) {
        //记录文件长度
        Long fileLength = file.length();
        //记录读出来的文件的内容
        byte[] fileContext = new byte[fileLength.intValue()];
        FileInputStream in = null;
        PrintWriter out = null;
        String name = file.getName();
        if (name.contains(".")) {
            name = name.substring(0, name.indexOf("."));
        }
        try {
            in = new FileInputStream(file);
            //读出文件全部内容(内容和文件中的格式一致,含换行)
            in.read(fileContext);
            // 避免出现中文乱码
            String str = new String(fileContext, "utf-8");
            //修改对应字符串内容
            str = isContainChinese(str, name, prefex);
            //再把新的内容写入文件
            out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), "utf-8"));

            if (!str.contains("import com.sskj.common.base.App;")){
                str=str.replaceFirst("(package[\\s\\S].*?;\\r\\n)", "$1import com.sskj.common.base.App;");
            }
            out.write(str);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                out.flush();
                out.close();
                in.close();
                index = 0;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static String useBufferIStream(File file) {
        String content = "";
        try {
            FileInputStream fis = new FileInputStream(file);
            BufferedInputStream bis = new BufferedInputStream(fis);
            byte[] buffer = new byte[1024];
            int cnt = 0;
            while ((cnt = bis.read(buffer)) != -1) {
                String block = new String(buffer, 0, cnt);
                content += block;
            }
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return content;

    }


    /**
     * 读取xml文件
     *
     * @param file
     */
    public static void readXml(File file, String prefix) {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = null;
        try {
            builder = dbf.newDocumentBuilder();
            Document document = builder.parse(file);
            String name = file.getName();
            if (name.contains(".")) {
                name = name.substring(0, name.indexOf("."));
            }
            realDocument = document;
            readNode(document.getFirstChild(), name, prefix);
            saveXml(file.getPath(), realDocument);
        } catch (ParserConfigurationException | SAXException | IOException e) {
            e.printStackTrace();
        }
    }


    public static void readNode(Node node, String name, String prefix) {
        if (name.contains(".")) {
            name = name.substring(0, name.indexOf("."));
        }
        NodeList nodeList = node.getChildNodes();
        for (int i = 0; i < nodeList.getLength(); ++i) {
            Node nodetmp = nodeList.item(i);
            if (nodetmp.hasChildNodes()) {
                checkNode(nodetmp, name, prefix);
                readNode(nodetmp, name, prefix);
            } else {
                checkNode(nodetmp, name, prefix);
            }
        }

    }


    public static void checkNode(Node node, String name, String prefix) {
        NamedNodeMap namedNodeMap = node.getAttributes();
        if (namedNodeMap != null) {
            for (int j = 0; j < namedNodeMap.getLength(); ++j) {
                Node node2 = namedNodeMap.item(j);
                //如果当前行含有text
                if (node2.getNodeName().toLowerCase().contains("text") || node2.getNodeName().contains("title") || node2.getNodeName().contains("hint")) {
                    //获取对应的值
                    String value = node2.getNodeValue();
                    //检查是否需要替换值
                    String realValue = checkXmlChinese(prefix + name + index + salt, value);
                    //如果需要，替换并保存
                    if (!value.equals(realValue)) {
                        NodeList nodeList = realDocument.getElementsByTagName(node.getNodeName());
                        for (int i = 0; i < nodeList.getLength(); i++) {
                            Element element = (Element) nodeList.item(i);
                            //根据原始值查找到当前元素
                            if (element.getAttribute(node2.getNodeName()).equals(value)) {
                                element.setAttribute(node2.getNodeName(), realValue);
                            }
                        }
                    }
                }
            }
        }

    }


    public static String checkXmlChinese(String name, String text) {
        String t = "[\\u4e00-\\u9fa5]+";
        Pattern p = Pattern.compile(t);
        Matcher m = p.matcher(text);
        String result = text;
        if (m.find()) {
            String chinese = text;
            String newName = cacheName(chinese, format(name));
            System.out.print("find>>>>" + chinese + "\n");
            System.out.print("Replace>>>>" + newName + "\n");
            result = text.replace(chinese, "@string/" + newName);
            index++;
        }
        return result;
    }

    /**
     * 把要替换的name和value保存到map中
     * <p>
     * 检测map中是否有相同的value，如果有则返回对应的name
     * 如果没有则 保存到map中并返回传入的name;
     *
     * @param value
     * @param name
     * @return
     */
    public static String cacheName(String value, String name) {
        for (String v : exitName.keySet()) {
            if (exitName.get(v).equals(value)) {
                return v;
            }
        }
        exitName.put(name, value);
        nameTemp.put(name, value);
        return name;
    }


    public static String format(String text) {
        StringBuilder result = new StringBuilder();
        result.append(text.substring(0, 1).toLowerCase());
        result.append(text.substring(1));
        return result.toString();
    }


    public static void readExitString(String basePath) {
        exitName.clear();
        String path = basePath + "/src/main/res/values/strings.xml";
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder builder = dbf.newDocumentBuilder();
            Document document = builder.parse(path);
//            //查找是否相同
            NodeList stringList = document.getElementsByTagName("string");
            for (int j = 0; j < stringList.getLength(); j++) {
                Node node = stringList.item(j);
                Element element = (Element) node;
                String name = element.getAttribute("name");
                String value = element.getTextContent();
                exitName.put(name, value);
            }
        } catch (ParserConfigurationException | SAXException | IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 将map写入到string.xml中
     */
    public static void editString(String basePath) {
        String path = basePath + "/src/main/res/values/strings.xml";
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder builder = dbf.newDocumentBuilder();
            Document document = builder.parse(path);
//            //查找是否相同
//            NodeList stringList = document.getElementsByTagName("string");
//            for (int j = 0; j < stringList.getLength(); j++) {
//                Node string = stringList.item(j);
//                if (string.getNodeValue().equals(value)) {
//                    NamedNodeMap attributes = string.getAttributes();
//                }
//            }
            NodeList nodeList = document.getElementsByTagName("resources");
            Node node = nodeList.item(0);
            for (String v : nameTemp.keySet()) {
                Element resources = (Element) node;
                Element string = document.createElement("string");
                string.setAttribute("name", v);
                string.setNodeValue(nameTemp.get(v));
                string.setTextContent(nameTemp.get(v));
                resources.appendChild(string);
            }
            saveXml(path, document);
        } catch (ParserConfigurationException | SAXException | IOException e) {
            e.printStackTrace();
        }

    }


    public static void saveXml(String path, Document doc) {//将Document输出到文件
        TransformerFactory transFactory = TransformerFactory.newInstance();
        try {
            Transformer transformer = transFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            DOMSource source = new DOMSource(doc);
            StreamResult result = new StreamResult(new File(path));
            transformer.transform(source, result);
        } catch (TransformerException e) {
            e.printStackTrace();
        }
    }


    public static void printDocument(String path, Document doc) {
        TransformerFactory transFactory = TransformerFactory.newInstance();
        try {
            Transformer transformer = transFactory.newTransformer();
            transformer.setOutputProperty("indent", "yes");
            DOMSource source = new DOMSource();
            source.setNode(doc);
            StringWriter writer = new StringWriter();
            StreamResult result = new StreamResult(writer);
            result.setOutputStream(new FileOutputStream(path));
            System.out.print(writer.getBuffer().toString());
        } catch (TransformerException | FileNotFoundException e) {
            e.printStackTrace();
        }
    }


}